package com.codi.bus.core.config;

import com.google.common.cache.CacheBuilder;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
import org.springframework.cache.guava.GuavaCacheManager;
import org.springframework.cache.interceptor.CacheErrorHandler;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.cache.interceptor.SimpleKeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.cache.DefaultRedisCachePrefix;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 模块名
 *
 * @author spy
 * @version 1.0 2017-11-30 11:21
 * @since 1.0
 */
@Slf4j
@Component
public class CacheConfig {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Bean
    public CacheManager cacheManager() {
        // 默认redis缓存，永远不过期
        RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
        cacheManager.setUsePrefix(true);
        cacheManager.setCachePrefix(new DefaultRedisCachePrefix());

        //启动时从远程加载cache
        //cacheManager.setLoadRemoteCachesOnStartup(true);


        long ONE_DAY = 24 * 60 * 60;

        // 可以设置对应key region的失效实现
        Map<String, Long> expires = Maps.newHashMap();
        expires.put("user", ONE_DAY); // user region 1天的有效期

        cacheManager.setExpires(expires);

        return cacheManager;
    }


    @Bean
    public KeyGenerator keyGenerator() {
        // key生成策略，支持SPEL
        return new SimpleKeyGenerator();
    }

    @Bean
    public CacheErrorHandler errorHandler() {

        CacheErrorHandler handler = new CacheErrorHandler() {
            @Override
            public void handleCacheGetError(RuntimeException exception, Cache cache, Object key) {
                log.error("fail to get cache", exception);
                log.error("cache key={}", key);
            }

            @Override
            public void handleCachePutError(RuntimeException exception, Cache cache, Object key, Object value) {
                log.error("fail to put cache", exception);
                log.error("cache key={},value={}", key, value);
            }

            @Override
            public void handleCacheEvictError(RuntimeException exception, Cache cache, Object key) {
                log.error("fail to evict cache", exception);
                log.error("cache key={}", key);
            }

            @Override
            public void handleCacheClearError(RuntimeException exception, Cache cache) {
                log.error("fail to clear cache", exception);
                log.error("cache name={}", cache.getName());
            }
        };

        return handler;
    }

    @Bean
    public CacheManager localMapTimeoutCacheManager() {
        GuavaCacheManager cacheManager = new GuavaCacheManager();
        CacheBuilder<Object, Object> cacheBuilder = CacheBuilder.newBuilder()
                                                                .maximumSize(200)
                                                                .expireAfterWrite(1, TimeUnit.DAYS);
        cacheManager.setCacheBuilder(cacheBuilder);
        return cacheManager;
    }

    @Bean
    public CacheManager localCacheManager() {
        GuavaCacheManager cacheManager = new GuavaCacheManager();

        return cacheManager;
    }

    @Bean
    public CacheManager localMapCacheManager() {
        CacheManager cacheManager = new ConcurrentMapCacheManager();

        return cacheManager;
    }
}
